/**
 * Alipay.com Inc.
 * Copyright (c) 2005-2008 All Rights Reserved.
 */
package com.alipay.client.trade;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alipay.client.base.PartnerConfig;
import com.alipay.client.base.ResponseResult;
import com.alipay.client.base.TradeConfig;
import com.alipay.client.security.MD5Signature;
import com.alipay.client.util.EncodeUtils;
import com.alipay.client.util.ParameterUtil;
import com.alipay.client.util.StringUtil;
import com.alipay.client.util.XMapUtil;
import com.alipay.client.vo.DirectTradeCreateRes;
import com.alipay.client.vo.ErrorCode;
import com.boxin.ims.modules.wechat.utils.SpringUtils;
import com.zhixun.mobile.common.utils.EncryptUtils;
import com.zhixun.mobile.modules.goods.service.GoodsService;

/**
 * 
 * ����֧�����Ŀ���ƽ̨������֧�����ײ���
 * 
 * 1.��ҵ������ⲿ���׺š���Ʒ��ơ���Ʒ�ܼۡ������ʻ��������ʻ���notify_url��Щ��������xml �ĸ�ʽ����<req_data></req_data>��
 * 2.��ͨ�ò���Ҳ������������� 3.�����ϵĲ������ǩ��ǩ����Ҳ�������������
 * 4.����֧��������ƽ̨��alipay.wap.trade.create.direct����
 * 5.�ӿ���ƽ̨���ص�������ȡ��request_token���Է��ص�����Ҫ����˽Կ���ܣ�����֧�����Ĺ�Կ��ǩ��
 * 6.ʹ���õ���request_token��װalipay.wap.auth.authAndExecute�������תurl
 * 7.�����װ������url��ת��֧�����Ŀ���ƽ̨ҳ�棬���״�����֧����֧������ҳ�������
 * 
 * 
 * @author 3y
 * @version $Id: Trade.java, v 0.1 2011-08-22 ����17:52:02 3y Exp $
 */
public class Trade extends HttpServlet {

	private static final long serialVersionUID = -3035307235076650766L;
	private static final String SEC_ID="MD5";
	String basePath="";
	public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException {
	    doPost(request,response);
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
	  //�õ�Ӧ�÷�������ַ
        String path = request.getContextPath();
        basePath = request.getScheme() + "://" + request.getLocalAddr() + ":"
                                   + request.getServerPort() + path + "/";
		Map<String, String> reqParams = prepareTradeRequestParamsMap(request);
		//ǩ������ 
		String signAlgo = SEC_ID;
		String reqUrl = TradeConfig.REQ_URL;
		
		//��ȡ�̻�MD5 key
		String key = PartnerConfig.KEY;
		String sign = sign(reqParams,signAlgo,key);
		reqParams.put("sign", sign);
		
		ResponseResult resResult = new ResponseResult();
		String businessResult = "";
		try {
			resResult = send(reqParams,reqUrl,signAlgo);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		if (resResult.isSuccess()) {
			businessResult = resResult.getBusinessResult();
		} else {
			return;
		}
		DirectTradeCreateRes directTradeCreateRes = null;
		XMapUtil.register(DirectTradeCreateRes.class);
		try {
			directTradeCreateRes = (DirectTradeCreateRes) XMapUtil
					.load(new ByteArrayInputStream(businessResult
							.getBytes("UTF-8")));
		} catch (UnsupportedEncodingException e) {
		} catch (Exception e) {
		}
		// ����ƽ̨���ص�������ȡ��request_token
		String requestToken = directTradeCreateRes.getRequestToken();
		Map<String, String> authParams = prepareAuthParamsMap(request,
				requestToken);
		//�Ե�����Ȩ�������ǩ��
		String authSign = sign(authParams,signAlgo,key);
		authParams.put("sign", authSign);
		String redirectURL = "";
		try {
			redirectURL = getRedirectUrl(authParams,reqUrl);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (StringUtil.isNotBlank(redirectURL)) {
			response.sendRedirect(redirectURL);
			return;
		}
	}
	
	
	
	/**
	 * ׼��alipay.wap.trade.create.direct����Ĳ���
	 * 
	 * @param request
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private Map<String, String> prepareTradeRequestParamsMap(
			HttpServletRequest request) throws UnsupportedEncodingException {
		Map<String, String> requestParams = new HashMap<String, String>();
		
		request.setCharacterEncoding("utf-8");
		
		
		/**
		 * ���ղ���ʼ
		 */
		String goodsId	 = request.getParameter("gid");		//��ƷID
		String goodsName = request.getParameter("gn");		//��Ʒ�� ��
		String goodsFee  = request.getParameter("gf");		//��Ʒ�۸�
		String encodeGid  = request.getParameter("gidcode");		//��Ʒ�۸�
		String encodeName = request.getParameter("gncode");		//��Ʒ��Ƽ�����
		String encodeFee  = request.getParameter("gfcode");		//��Ʒ�۸������
		String sellerId   = request.getParameter("uid");		//�̼�ID
		String encodeSellerId = request.getParameter("uidcode");		//�̼�ID����
		String securityCode =  request.getParameter("scode");		//���ܰ�ȫ��
		
		if(EncryptUtils.MD5EncodeString(goodsId+EncodeUtils.GOODS_ID_ENCODE_KEY).equals(encodeGid)){
			System.out.println("�����ǺϷ���");
		}
		GoodsService goodsService = (GoodsService) SpringUtils.getBean("goodsService");
		Map<String,Object> resultMap = 	goodsService.getGoodsById(Long.parseLong(goodsId));
		
		goodsName = resultMap.get("name").toString();
		goodsFee = resultMap.get("price").toString();
		/**
		 * ���ղ������
		 */
		
		
		
		
		// ��Ʒ���
		String subject = goodsName;
		// ��Ʒ�ܼ�
        String totalFee = goodsFee;
        // �ⲿ���׺� ����ȡ��ǰʱ�䣬�̻��ɸ���Լ�������޸Ĵ˲����֤Ψһ��
        String outTradeNo = System.currentTimeMillis()+"";
		// �����ʺ�
		String sellerAccountName =PartnerConfig.SELLER;
		
		// ����֧�������͵�֪ͨ��url
		String notifyUrl = basePath+"servlet/NotifyReceiver";
		// δ���֧�����û�������ӷ����̻�url
		String merchantUrl = basePath;
		// req_data������
		String reqData = "<direct_trade_create_req>" + "<subject>" + subject
				+ "</subject><out_trade_no>" + outTradeNo
				+ "</out_trade_no><total_fee>" + totalFee
				+ "</total_fee><seller_account_name>" + sellerAccountName
				+ "</seller_account_name><notify_url>" + notifyUrl
				+ "</notify_url><call_back_url>" + merchantUrl+ "</call_back_url>";
		        reqData = reqData + "</direct_trade_create_req>";
		requestParams.put("req_data", reqData);
		requestParams.put("req_id", System.currentTimeMillis() + "");
		requestParams.putAll(prepareCommonParams(request));
		return requestParams;
	}
	
	

	/**
	 * ׼��alipay.wap.auth.authAndExecute����Ĳ���
	 * 
	 * @param request
	 * @param requestToken
	 * @return
	 */
	private Map<String, String> prepareAuthParamsMap(
			HttpServletRequest request, String requestToken) {
		Map<String, String> requestParams = new HashMap<String, String>();
		String reqData = "<auth_and_execute_req><request_token>" + requestToken
				+ "</request_token></auth_and_execute_req>";
		requestParams.put("req_data", reqData);
		requestParams.putAll(prepareCommonParams(request));
        //֧���ɹ���ת����
		String callbackUrl = basePath+"servlet/CallBack";
		requestParams.put("call_back_url", callbackUrl);
		requestParams.put("service", "alipay.wap.auth.authAndExecute");
		return requestParams;
	}

	/**
	 * ׼��ͨ�ò���
	 * 
	 * @param request
	 * @return
	 */
	private Map<String, String> prepareCommonParams(HttpServletRequest request) {
		Map<String, String> commonParams = new HashMap<String, String>();
		commonParams.put("service", "alipay.wap.trade.create.direct");
		commonParams.put("sec_id", SEC_ID);
		commonParams.put("partner", PartnerConfig.PARTNER);
		String callBackUrl = basePath+"servlet/CallBack";
		commonParams.put("call_back_url", callBackUrl);
		commonParams.put("format", "xml");
		commonParams.put("v", "2.0");
		return commonParams;
	}

	/**
	 * �Բ������ǩ��
	 * 
	 * @param reqParams
	 * @return
	 */
	private String sign(Map<String, String> reqParams,String signAlgo,String key) {

		String signData = ParameterUtil.getSignData(reqParams);
		
		String sign = "";
		try {
			sign = MD5Signature.sign(signData, key);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return sign;
	}

	/**
	 * ����alipay.wap.auth.authAndExecute�����ʱ����Ҫ��ת��֧������ҳ�棬��װ��תurl
	 * 
	 * @param reqParams
	 * @return
	 * @throws Exception
	 */
	private String getRedirectUrl(Map<String, String> reqParams,String reqUrl)
			throws Exception {
		String redirectUrl = reqUrl + "?";
		redirectUrl = redirectUrl + ParameterUtil.mapToUrl(reqParams);
		return redirectUrl;
	}

	/**
	 * ����֧��������ƽ̨�ķ���
	 * 
	 * @param reqParams
	 *            �������
	 * @return
	 * @throws Exception
	 */
	private ResponseResult send(Map<String, String> reqParams,String reqUrl,String secId) throws Exception {
		String response = "";
		String invokeUrl = reqUrl  + "?";
		URL serverUrl = new URL(invokeUrl);
		HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();

		conn.setRequestMethod("POST");
		conn.setDoOutput(true);
		conn.connect();
		String params = ParameterUtil.mapToUrl(reqParams);
		conn.getOutputStream().write(params.getBytes());

		InputStream is = conn.getInputStream();

		BufferedReader in = new BufferedReader(new InputStreamReader(is));
		StringBuffer buffer = new StringBuffer();
		String line = "";
		while ((line = in.readLine()) != null) {
			buffer.append(line);
		}
		response = URLDecoder.decode(buffer.toString(), "utf-8");
		conn.disconnect();
		return praseResult(response,secId);
	}

	/**
	 * ����֧�������صĽ��
	 * 
	 * @param response
	 * @return
	 * @throws Exception
	 */
	private ResponseResult praseResult(String response,String secId) throws Exception {
		// ���óɹ�
		HashMap<String, String> resMap = new HashMap<String, String>();
		String v = ParameterUtil.getParameter(response, "v");
		String service = ParameterUtil.getParameter(response, "service");
		String partner = ParameterUtil.getParameter(response, "partner");
		String sign = ParameterUtil.getParameter(response, "sign");
		String reqId = ParameterUtil.getParameter(response, "req_id");
		resMap.put("v", v);
		resMap.put("service", service);
		resMap.put("partner", partner);
		resMap.put("sec_id", secId);
		resMap.put("req_id", reqId);
		String businessResult = "";
		ResponseResult result = new ResponseResult();
		System.out.println("Token Result:"+response);
		if (response.contains("<err>")) {
			
			result.setSuccess(false);
			businessResult = ParameterUtil.getParameter(response, "res_error");

			// ת��������Ϣ
			XMapUtil.register(ErrorCode.class);
			ErrorCode errorCode = (ErrorCode) XMapUtil
					.load(new ByteArrayInputStream(businessResult
							.getBytes("UTF-8")));
			result.setErrorMessage(errorCode);

			resMap.put("res_error", ParameterUtil.getParameter(response,
					"res_error"));
		} else {
		    businessResult = ParameterUtil.getParameter(response, "res_data");
            result.setSuccess(true);
            result.setBusinessResult(businessResult);
            resMap.put("res_data", businessResult);
		}
		//��ȡ��ǩ�����
		String verifyData = ParameterUtil.getSignData(resMap);
		//�Դ�ǩ�����ʹ��֧������Կ��ǩ��
		boolean verified = MD5Signature.verify(verifyData,sign,PartnerConfig.KEY);
		
		if (!verified) {
			throw new Exception("��֤ǩ��ʧ��");
		}
		return result;
	}
}
